package com.eduagent.xwqeduagent.api.RecordingFileTranscription.util;

import com.eduagent.xwqeduagent.api.RecordingFileTranscription.constant.FileTranscriptionConstant;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.Date;

/**
 * 讯飞录音文件转写API签名工具类
 * 严格按照官方demo实现
 */
public class SignatureUtil {

    /**
     * 生成签名
     * 
     * @param ts 时间戳
     * @return 签名字符串
     * @throws Exception 签名过程中的异常
     */
    public static String generateSignature(long ts) throws Exception {
        String appId = FileTranscriptionConstant.APP_ID;
        String secretKey = FileTranscriptionConstant.SECRET_KEY;
        
        // 1. 获取baseString (appid和当前时间戳ts拼接)
        String baseString = appId + ts;
        
        // 2. 对baseString进行MD5，得到32位小写的md5值
        String md5Str = md5Encrypt(baseString);
        
        // 3. 以secretKey为key对MD5后的字符串进行HmacSHA1加密并返回Base64编码结果
        String signa = hmacSha1AndBase64(md5Str, secretKey);
        
        // 4. 无需URLEncode，直接返回Base64结果
        return signa;
    }
    
    /**
     * MD5加密，直接返回32位小写字符串，与讯飞官方demo一致
     * 
     * @param str 原始字符串
     * @return MD5加密后的32位小写字符串
     * @throws Exception 加密过程中的异常
     */
    private static String md5Encrypt(String str) throws Exception {
        try {
            byte[] btInput = str.getBytes(StandardCharsets.UTF_8);
            MessageDigest mdInst = MessageDigest.getInstance("MD5");
            mdInst.update(btInput);
            byte[] md = mdInst.digest();
            
            // 把密文转换成32位的十六进制小写字符串形式
            int j = md.length;
            char[] chars = new char[j * 2];
            int k = 0;
            for (byte byte0 : md) {
                chars[k++] = hexDigits[byte0 >>> 4 & 0xf];
                chars[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(chars);
        } catch (NoSuchAlgorithmException e) {
            throw new Exception("MD5加密错误:" + e.getMessage());
        }
    }
    
    /**
     * HMAC-SHA1加密并进行Base64编码
     * 
     * @param data 待加密数据
     * @param key 密钥
     * @return 加密并Base64编码后的字符串
     * @throws Exception 加密过程中的异常
     */
    private static String hmacSha1AndBase64(String data, String key) throws Exception {
        try {
            byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8);
            SecretKeySpec signingKey = new SecretKeySpec(keyBytes, "HmacSHA1");
            
            Mac mac = Mac.getInstance("HmacSHA1");
            mac.init(signingKey);
            
            byte[] rawHmac = mac.doFinal(data.getBytes(StandardCharsets.UTF_8));
            return Base64.getEncoder().encodeToString(rawHmac);
        } catch (Exception e) {
            throw new Exception("HMAC-SHA1加密错误:" + e.getMessage());
        }
    }
    
    // 用于MD5转换的字符
    private static final char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 
                                            'a', 'b', 'c', 'd', 'e', 'f'};
    
    /**
     * 检查并打印当前系统时间，用于调试
     */
    public static void printCurrentTime() {
        long currentTime = System.currentTimeMillis();
        System.out.println("当前系统时间: " + new Date());
        System.out.println("当前时间戳(毫秒): " + currentTime);
        System.out.println("当前时间戳(秒): " + currentTime / 1000);
    }
} 